package com.cxd.performance.service.impl;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class CompletableFutureServiceImpl {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //CompletableFuture.thenApply():把前面的执行结果，交给后面的function
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            int result = 100;
            System.out.println("第一次运算：" + result);
            return result;
        }).thenApply(number -> {
            int result = number * 3;
            System.out.println("第二次运算：" + result);
            return result;
        });
        Integer integer = completableFuture.get();
        System.out.println("最终结果：" + integer);
        System.out.println("====================================================================================");
        //CompletableFuture.thenCompose():
        CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

            @Override
            public Integer get() {
                int number = new Random().nextInt(30);
                System.out.println("第一次运算：" + number);
                return number;
            }
        }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {

            @Override
            public CompletionStage<Integer> apply(Integer param) {
                return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                    @Override
                    public Integer get() {
                        int number = param * 2;
                        System.out.println("第二次运算：" + number);
                        return number;
                    }
                });
            }
        });
        System.out.println(completableFuture1.get());
        System.out.println("============================================================================================");
        //CompletableFuture.thenAcceptBoth
        CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(3) + 1;
                System.out.println("任务1结果" + number);
                return number;
            }
        });
        CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(3) + 1;
                System.out.println("任务2结果" + number);
                return number;
            }
        });
        completableFuture2.thenAcceptBoth(completableFuture3, new BiConsumer<Integer, Integer>() {
            @Override
            public void accept(Integer x, Integer y) {
                System.out.println("最终结果：" + (x + y));
            }
        });
        System.out.println("============================================================================================");
        //CompletableFuture.thenRun
        CompletableFuture.supplyAsync(() -> {
            int number = new Random().nextInt(10);
            System.out.println("第一阶段：" + number);
            return number;
        }).thenRun(() -> {
            System.out.println("thenRun执行");
        });
        System.out.println("============================================================================================");
        //CompletableFuture.thenCombine
        CompletableFuture<Integer> completableFuture4 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(10);
                System.out.println("任务1结果：" + number);
                return number;
            }
        });
        CompletableFuture<Integer> completableFuture5 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(10);
                System.out.println("任务2结果：" + number);
                return number;
            }
        });
        CompletableFuture<Integer> completableFuture6 = completableFuture4.thenCombine(completableFuture5, new BiFunction<Integer, Integer, Integer>() {
            @Override
            public Integer apply(Integer x, Integer y) {
                return x + y;
            }
        });
        System.out.println("组合后结果：" + completableFuture6.get());

        //CompletableFuture.applyToEither
        System.out.println("============================================================================================");
        CompletableFuture<Integer> completableFuture7 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(10);
                System.out.println("任务1结果：" + number);
                return number;
            }
        });
        CompletableFuture<Integer> completableFuture8 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int number = new Random().nextInt(10);
                System.out.println("任务2结果：" + number);
                return number;
            }
        });
        CompletableFuture<Integer> completableFuture9 = completableFuture7.applyToEither(completableFuture8, new Function<Integer, Integer>() {

            @Override
            public Integer apply(Integer number) {
                System.out.println("最快结果：" + number);
                return number * 2;
            }
        });
        System.out.println(completableFuture9.get());
        System.out.println("============================================================================================");

        //CompletableFuture.allOf
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("future1完成！");
            return "future1完成！";
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("future2完成！");
            return "future2完成！";
        });
        CompletableFuture.allOf(future1, future2);
        System.out.println(future1.get());
        System.out.println(future2.get());
    }
}
